package eg.edu.eelu.fyp2013.jdetector.core.classifier;

import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

import com.mathworks.toolbox.javabuilder.MWException;
import com.mathworks.toolbox.javabuilder.MWNumericArray;

import matlabcontrol.MatlabConnectionException;
import matlabcontrol.MatlabInvocationException;
import matlabcontrol.MatlabProxy;
import matlabcontrol.MatlabProxyFactory;
import matlabcontrol.extensions.MatlabNumericArray;
import matlabcontrol.extensions.MatlabTypeConverter;
import eg.edu.eelu.fyp2013.jdetector.core.input_output.ClassiferData;
import FullKLDA.*;

public class KLDAPlusEuclidanDist {
	
	
	public double []  classifykernalplusdistance (ClassiferData [] Learned , ClassiferData [] Tested 
			) throws MWException
	{
	
		
		double [][] LearnedMatrix = new double [Learned.length][Learned[0].Allreduceddata.size()];
        double [][] learnedlabels = new double [Learned.length][1];
		for(int i = 0; i < Learned.length; i++)
		{
			for(int j = 0; j < Learned[i].Allreduceddata.size(); j++)
			{
				LearnedMatrix[i][j] = Learned[i].Allreduceddata.get(j);
			}
		    learnedlabels[i][0] = Learned[i].label; 
			
		}
		
		double [][] TestedMatrix = new double [Tested.length][Tested[0].Allreduceddata.size()];

		for(int i = 0; i < Tested.length; i++)
		{
			for(int j = 0; j < Tested[i].Allreduceddata.size(); j++)
			{
				TestedMatrix[i][j] = Tested[i].Allreduceddata.get(j);
			}
			
		}
		
	    //processor.setNumericArray("Learn", new MatlabNumericArray(LearnedMatrix,null));
	   // processor.setNumericArray("Test", new MatlabNumericArray(TestedMatrix,null));
	    //processor.setNumericArray("labels", new MatlabNumericArray(learnedlabels,null));
		  Object [] KD = new Object [3];
		  TotalKLDA Fklda = new TotalKLDA();
		  KD[0] = LearnedMatrix;
		  KD[1] = TestedMatrix;
		  KD[2] = learnedlabels;
		  
		  
	       
		  MWNumericArray [] M = new MWNumericArray[1];
		  
		  double [] ANNresult = new double [7];
	      
		  Fklda.KLDA(M, KD); 
		  
		  
		  
		  double [] onedistance = M[0].getDoubleData();
	   // proxy.eval("[Distance] = KLDA(Learn,Test,labels)");
	    
	    //double [][] Distancevalues = processor.getNumericArray("Distance").getRealArray2D();
	    
		  double [][] Distancevalues = new double [Tested.length][Learned.length];
	    int count = 0;
	    for(int i = 0; i < Tested.length; i++)
	    {
	    	for(int j = 0 ; j < Learned.length; j++)
	    	{
	            Distancevalues[i][j] = onedistance[count];
	    		count++;
	    	}
	    	
	    }
	    
	    double minlabel;
	    for(int i = 0 ; i < Tested.length; i++)
	    {
	    	double mindistance = Distancevalues[i][0];
	    	minlabel = learnedlabels[0][0];
	    	for(int j = 1 ; j < Learned.length; j++)
	    	{
	    		if(Distancevalues[i][j]  <=  mindistance)
	    		{
	    			mindistance = Distancevalues[i][j];
	    			minlabel = learnedlabels[j][0];
	    		}
	    		 		
	    		
	    	}
	    	
	    	//  minlabel actual value;
	    	// testedlabel desired value;
			
			//ANNresult [0] // TP
			//ANNresult [1] // TN 
			//ANNresult [2] // FP
			//ANNresult [3] // FN
			//ANNresult [4] // Sen
			//ANNresult [5] // Spec
			//ANNresult [6] // Acc
	    	
	    	
	    	if(Tested[i].label == 1)
		     {
		    	 if(minlabel != Tested[i].label)
		    	 {
		    		 ANNresult[3]++;
		    	 }
		    	 if(minlabel == Tested[i].label)
		    	 {
		    		 ANNresult[0]++;
		    	 }
		    		 
		    	 
		     }
		     if(Tested[i].label == 0)
		     {
		    	 if(minlabel == Tested[i].label)
		    	 {
		    		 ANNresult[1]++;
		    	 }
		    	 if(minlabel != Tested[i].label)
		    	 {
		    		 ANNresult[2]++;
		    	 }
		     }
	    }
	 // (TP / TP + FN) * 100;
	     //sen
	     ANNresult[4] = (ANNresult[0] / (ANNresult[0] + ANNresult[3])) * 100;
	    //TN / (FP + TN ) * 100  
	     //spec
	     ANNresult[5] = (ANNresult[1] / (ANNresult[2] + ANNresult[1])) * 100;
	    // Acc
	     //(TN + TP)/(TN+TP+FN+FP)
	     ANNresult[6] = ((ANNresult[1] + ANNresult[0])/ (ANNresult[2] + ANNresult[0] + ANNresult[3] + ANNresult[1])) * 100;
	     
	    
	    return ANNresult;
	    // All distances 
	    
	    
	    
	    
		
		
		
	}
	public void  Savelearnedfeaturesandlabel (ClassiferData [] learned) throws IOException
	{
		FileWriter File = new FileWriter("ClassifiedLearneddata");
		PrintWriter pw = new PrintWriter(File);
		
		pw.println(learned.length);
		for(int i = 0 ; i < learned.length; i++)
		{
			
			for(int j = 0; j < learned[i].Allreduceddata.size() ; j++)
			{
				 
				pw.print(learned[i].Allreduceddata.get(j) + " " + ",");
			}
			pw.print("=" + learned[i].label);
			pw.println();
		}
		File.close();
		pw.close();
		
	}

}
